{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Title: #入场安检"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Difficulty: #Hard"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Category Title: #Algorithms"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Tag Slug: #array #dynamic-programming"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Name Translated: #数组 #动态规划"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solution Name: securityCheck"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Translated Title: #入场安检"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Translated Content:\n",
    "「力扣挑战赛」 的入场仪式马上就要开始了，由于安保工作的需要，设置了可容纳人数总和为 `M` 的 `N` 个安检室，`capacities[i]` 记录第 `i` 个安检室可容纳人数。安检室拥有两种类型：\n",
    "- 先进先出：在安检室中的所有观众中，最早进入安检室的观众最先离开\n",
    "- 后进先出：在安检室中的所有观众中，最晚进入安检室的观众最先离开\n",
    "\n",
    "![c24754f1a5ff56989340ba5004dc5eda.gif](https://pic.leetcode-cn.com/1628843202-cdFPSt-c24754f1a5ff56989340ba5004dc5eda.gif)\n",
    "\n",
    "\n",
    "\n",
    "恰好 `M+1` 位入场的观众（编号从 0 开始）需要排队**依次**入场安检， 入场安检的规则如下：\n",
    "- 观众需要先进入编号 `0` 的安检室\n",
    "- 当观众将进入编号 `i` 的安检室时（`0 <= i < N`)，\n",
    "    - 若安检室未到达可容纳人数上限，该观众可直接进入；\n",
    "    - 若安检室已到达可容纳人数上限，在该观众进入安检室之前需根据当前安检室类型选择一位观众离开后才能进入；\n",
    "- 当观众离开编号 `i` 的安检室时 （`0 <= i < N-1`)，将进入编号 `i+1` 的安检室接受安检。\n",
    "\n",
    "若可以任意设定每个安检室的类型，请问有多少种设定安检室类型的方案可以使得编号 `k` 的观众第一个通过最后一个安检室入场。\n",
    "\n",
    "\n",
    "**注意：** \n",
    "- 观众不可主动离开安检室，只有当安检室容纳人数达到上限，且又有新观众需要进入时，才可根据安检室的类型选择一位观众离开；\n",
    "- 由于方案数可能过大，请将答案对 `1000000007` 取模后返回。\n",
    "\n",
    "\n",
    "**示例 1：**\n",
    "> 输入：`capacities = [2,2,3], k = 2`\n",
    ">\n",
    "> 输出：`2`\n",
    "> 解释：\n",
    "> 存在两种设定的 `2` 种方案：\n",
    "> - 方案 1：将编号为 `0` 、`1` 的实验室设置为 **后进先出** 的类型，编号为 `2` 的实验室设置为 **先进先出** 的类型；\n",
    "> - 方案 2：将编号为 `0` 、`1` 的实验室设置为 **先进先出** 的类型，编号为 `2` 的实验室设置为 **后进先出** 的类型。\n",
    ">\n",
    "> 以下是方案 1 的示意图：\n",
    ">![c60e38199a225ad62f13b954872edf9b.gif](https://pic.leetcode-cn.com/1628841618-bFKsnt-c60e38199a225ad62f13b954872edf9b.gif)\n",
    "\n",
    "\n",
    "\n",
    "**示例 2：**\n",
    "> 输入：`capacities = [3,3], k = 3`\n",
    ">\n",
    "> 输出：`0`\n",
    "\n",
    "**示例 3：**\n",
    "> 输入：`capacities = [4,3,2,2], k = 6`\n",
    ">\n",
    "> 输出：`2`\n",
    "\n",
    "**提示:**\n",
    "+ `1 <= capacities.length <= 200`\n",
    "+ `1 <= capacities[i] <= 200`\n",
    "+ `0 <= k <= sum(capacities)`\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Description: [oPs9Bm](https://leetcode.cn/problems/oPs9Bm/description/)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Solutions: [oPs9Bm](https://leetcode.cn/problems/oPs9Bm/solutions/)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "test_cases = ['[2,2,3]\\n2', '[3,3]\\n3', '[4,3,2,2]\\n6']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def securityCheck(self, capacities: List[int], k: int) -> int:\n",
    "        dp = [0] * (k+1)\n",
    "        dp[0] = 1\n",
    "        for x in capacities:\n",
    "            for j in range(k, x-2, -1):\n",
    "                dp[j] = (dp[j] + dp[j - (x-1)]) % (10**9 +7)\n",
    "        return dp[k] % (10**9 +7)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def securityCheck(self, capacities: List[int], k: int) -> int:\n",
    "        dp = [0]*(k+1)\n",
    "        dp[0] = 1\n",
    "        for c in capacities:\n",
    "            c-=1\n",
    "            for s in range(k,c-1,-1):\n",
    "                dp[s] = (dp[s]+dp[s-c])%1000000007\n",
    "        return dp[k]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def securityCheck(self, capacities: List[int], k: int) -> int:\n",
    "        dp = [0] * (k + 1)\n",
    "        dp[0] = 1\n",
    "        for v in capacities:\n",
    "            v = v - 1\n",
    "            for i in range(k,v-1,-1):\n",
    "                dp[i] = (dp[i] + dp[i-v])%(10 ** 9 + 7)\n",
    "        return dp[k]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def securityCheck(self, capacities: List[int], k: int) -> int:\n",
    "        dp = [0 for _ in range(k+1)]\n",
    "        dp[0] = 1\n",
    "        MOD = 1000000007\n",
    "        for ci in capacities:\n",
    "            for j in range(k, ci - 2, -1):\n",
    "                dp[j] = (dp[j] + dp[j - ci + 1]) % MOD\n",
    "        return dp[k]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\r\n",
    "    def securityCheck(self, cap: List[int], k: int) -> int:\r\n",
    "        c = Counter([0])\r\n",
    "        for x in cap:\r\n",
    "            for s, v in [*c.items()]:\r\n",
    "                c[s + x - 1] += v\r\n",
    "        return c[k] % 1000000007"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def securityCheck(self, capacities: List[int], k: int) -> int:\n",
    "        m=1000000007\n",
    "        if k==0:\n",
    "            c=Counter(capacities)\n",
    "            x=c[1]\n",
    "            r=pow(2,x)%m\n",
    "            return r\n",
    "        y=Counter()\n",
    "        y[0]=1\n",
    "        n=len(capacities)\n",
    "        for i in range (0,n):\n",
    "            x=Counter()\n",
    "            for j in y:\n",
    "                x[j+capacities[i]-1]=y[j]\n",
    "            for j in x:\n",
    "                y[j]+=x[j]\n",
    "        return y[k]%m"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def securityCheck(self, capacities: List[int], k: int) -> int:\n",
    "        cap=list(map(lambda x: x-1,capacities))\n",
    "        #print(cap)\n",
    "        res=0\n",
    "        dp=[[0 for _ in range(k+1)]for _ in range(len(cap)+1)]\n",
    "        dp[0][0]=1\n",
    "        #print(dp)\n",
    "        for i in range(1,len(cap)+1):\n",
    "            for j in range(0,k+1):\n",
    "                dp[i][j]=dp[i-1][j]\n",
    "                if j>=cap[i-1]:\n",
    "                    dp[i][j]+=dp[i-1][j-cap[i-1]]\n",
    "        \n",
    "        return dp[-1][-1]%1000000007"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import List\n",
    "import collections\n",
    "\n",
    "class Solution:\n",
    "    def securityCheck(self, capacities: List[int], k: int) -> int:\n",
    "        n=len(capacities)\n",
    "        cum_cap=[0]*n\n",
    "        x=0\n",
    "        for i in range(n):\n",
    "            x+=capacities[i]\n",
    "            cum_cap[i]=x\n",
    "        M=cum_cap[n-1]\n",
    "\n",
    "        if n==1:\n",
    "            if k==M-1:\n",
    "                return 2\n",
    "            return 0\n",
    "        \n",
    "        MODX=1000000007\n",
    "\n",
    "        dp0=[[0 for _ in range(n)] for _ in range(M+1)]\n",
    "        dp1=[[0 for _ in range(n)] for _ in range(M+1)]\n",
    "\n",
    "        if k>=capacities[0]:\n",
    "            dp0[k+1][0]=1\n",
    "        if k+capacities[0]<=M:\n",
    "            dp1[k+capacities[0]][0]=1\n",
    "        for m in range(k+1,M+1):\n",
    "            for i in range(1,n):\n",
    "                if cum_cap[i]>m:\n",
    "                    continue\n",
    "                dp0[m][i]=(dp0[m-1][i-1]+dp1[m-1][i-1])%MODX\n",
    "                dp1[m][i]=(dp0[m-capacities[i]][i-1]+dp1[m-capacities[i]][i-1])%MODX\n",
    "        return (dp0[M][n-1]+dp1[M][n-1])%MODX"
   ]
  }
 ],
 "metadata": {},
 "nbformat": 4,
 "nbformat_minor": 2
}
